package com.budwk.app.sys.controllers.sys;

import cn.dev33.satoken.annotation.SaCheckLogin;
import cn.dev33.satoken.annotation.SaCheckPermission;
import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.lang.UUID;
import com.alibaba.fastjson.JSONObject;
import com.budwk.app.sys.dto.SysUnitUpdateDTO;
import com.budwk.app.sys.models.*;
import com.budwk.app.sys.services.*;
import com.budwk.app.sys.vo.SysUnitVO;
import com.budwk.app.util.adminUtils.CommonCheckUtils;
import com.budwk.starter.common.constant.GlobalConstant;
import com.budwk.starter.common.openapi.annotation.*;
import com.budwk.starter.common.openapi.enums.ParamIn;
import com.budwk.starter.common.page.Pagination;
import com.budwk.starter.common.result.Result;
import com.budwk.starter.common.result.ResultCode;
import com.budwk.starter.log.annotation.SLog;
import com.budwk.starter.security.utils.SecurityUtil;
import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.nutz.dao.Chain;
import org.nutz.dao.Cnd;
import org.nutz.ioc.loader.annotation.Inject;
import org.nutz.ioc.loader.annotation.IocBean;
import org.nutz.lang.Lang;
import org.nutz.lang.Strings;
import org.nutz.lang.util.NutMap;
import org.nutz.mvc.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.List;

/**
 * @author wizzer@qq.com
 */
@IocBean
@At("/platform/sys/unit")
@SLog(tag = "单位管理")
@ApiDefinition(tag = "单位管理")
@Slf4j
public class SysUnitController {
    @Inject
    private SysUnitService sysUnitService;
    @Inject
    private SysUserService sysUserService;
    @Inject
    private SysUnitUserService sysUnitUserService;
    @Inject
    private SysGroupService sysGroupService;
    @Inject
    private SysRoleService sysRoleService;
    @Inject
    private SysDictService sysDictService;

    @At
    @Ok("json")
    @GET
    @ApiOperation(name = "Vue3树形列表查询")
    @ApiImplicitParams(
            {
                    @ApiImplicitParam(name = "name", example = "", description = "单位名称"),
                    @ApiImplicitParam(name = "leaderName", example = "", description = "部门负责人")
            }
    )
    @ApiResponses(
            implementation = Pagination.class
    )
    @SaCheckPermission("sys.manage.unit")
    public Result<?> list(
            @Param("name") String name,
            @Param("leaderName") String leaderName) {
        Cnd cnd = Cnd.NEW();
        // 增加5级权限
        CommonCheckUtils.checkAreaRangeCnd(cnd);
        // 非管理员显示所属单位及下级单位
        if (!StpUtil.hasRole(GlobalConstant.DEFAULT_SYSADMIN_ROLECODE)) {
            Sys_user sysUser = sysUserService.fetch(Cnd.where(Sys_user::getId, "=", SecurityUtil.getUserId()));
            Sys_unit unit = sysUnitService.fetch(Cnd.where(Sys_unit::getId, "=", sysUser.getUnitId()));
            cnd.and("path", "like", unit.getPath() + "%");
        }
        if (Strings.isNotBlank(name)) {
            cnd.and("name", "like", "%" + name + "%");
        }
        if (Strings.isNotBlank(leaderName)) {
            cnd.and("leaderName", "like", "%" + name + "%");
        }
        cnd.and("disable", "!=", true);
        cnd.asc("location");
        cnd.asc("path");
        return Result.success().addData(sysUnitService.query(cnd));
    }


    @At("/child")
    @Ok("json")
    @GET
    @SaCheckPermission("sys.manage.unit")
    @ApiOperation(name = "Vue2获取列表树型数据")
    @ApiImplicitParams(
            {
                    @ApiImplicitParam(name = "pid", description = "父级ID")
            }
    )
    @ApiResponses
    public Result<?> getChild(@Param("pid") String pid, HttpServletRequest req) {
        List<Sys_unit> list = new ArrayList<>();
        List<NutMap> treeList = new ArrayList<>();
        if (StpUtil.hasRole(GlobalConstant.DEFAULT_SYSADMIN_ROLECODE)) {
            Cnd cnd = Cnd.NEW();
            if (Strings.isBlank(pid)) {
                cnd.and("parentId", "=", "").or("parentId", "is", null);
            } else {
                cnd.and("parentId", "=", pid);
            }
            cnd.asc("location").asc("path");
            cnd.and("disable", "!=", true);
            list = sysUnitService.query(cnd);
        } else {
            //如果非超级管理员,则查询所在单位的所属分公司
            if (Strings.isBlank(pid)) {
                list = sysUnitService.query(Cnd.where("id", "=", sysUnitService.getMasterCompanyId(SecurityUtil.getUnitId())).asc("location").asc("path"));
            } else {
                Cnd cnd = Cnd.NEW();
                cnd.and("parentId", "=", pid);
                cnd.asc("location").asc("path");
                cnd.and("disable", "!=", true);
                list = sysUnitService.query(cnd);
            }
        }
        for (Sys_unit unit : list) {
            NutMap map = Lang.obj2nutmap(unit);
            map.addv("expanded", false);
            map.addv("level1", false);
            map.addv("children", new ArrayList<>());
            map.addv("userNumber", sysUserService.count(Cnd.where("unitId", "=", unit.getId())));
            map.addv("allNumber", sysUserService.count(Cnd.where("unitPath", "like", unit.getPath() + "%")));
            treeList.add(map);
        }
        return Result.data(treeList);
    }


    @At("/create")
    @Ok("json")
    @POST
    @SaCheckPermission("sys.manage.unit.create")
    @SLog(value = "新建单位:${unit.name}")
    @ApiOperation(name = "新建单位")
    @ApiFormParams(
            implementation = Sys_unit.class
    )
    @ApiResponses
    public Result<?> create(@Param("..") Sys_unit unit, HttpServletRequest req) {
        unit.setCreatedBy(SecurityUtil.getUserId());
        sysUnitService.save(unit);

        return Result.success();
    }

    @At("/delete/{id}")
    @Ok("json")
    @DELETE
    @SaCheckPermission("sys.manage.unit.delete")
    @SLog(value = "删除单位:")
    @ApiOperation(name = "删除单位")
    @ApiImplicitParams(
            {
                    @ApiImplicitParam(name = "id", description = "主键ID", in = ParamIn.PATH)
            }
    )
    @ApiResponses
    public Result<?> delete(String id, HttpServletRequest req) {
        Sys_unit unit = sysUnitService.fetch(id);
        if (unit == null) {
            return Result.error(ResultCode.NULL_DATA_ERROR);
        }
        req.setAttribute("_slog_msg", unit.getName());
        if (Strings.sNull(unit.getPath()).equals("0001")) {
            return Result.error("禁止删除");
        }

        // wzy 2023-10-23 判断单位下是否还有用户 如果有用户不能删除
        Cnd userCnd = Cnd.NEW();
        userCnd.and("unitPath", "like", unit.getPath() + "%");
        int userCount = sysUserService.count(userCnd);
        if (userCount > 0) Result.error("单位用户不为空，不能删除");

        sysUnitService.deleteAndChild(unit);

        // 也需要删除对应的字典表
        Cnd dictCnd = Cnd.NEW();
        dictCnd.and("unitid", "=", unit.getId());
        List<Sys_dict> dictList = sysDictService.query(dictCnd);
        for (Sys_dict sysDict : dictList) {
            sysDictService.deleteAndChild(sysDict);
        }
        return Result.success();
    }

    @At("/get/{id}")
    @Ok("json:{locked:'^(password|salt|mobile|email)$'}")
    @GET
    //@SaCheckPermission("sys.manage.unit")
    @ApiOperation(name = "获取单位信息")
    @ApiImplicitParams(
            {
                    @ApiImplicitParam(name = "id", description = "主键ID", in = ParamIn.PATH)
            }
    )
    @ApiResponses
    @SaCheckLogin
    public Result<?> getData(String id, HttpServletRequest req) {
        Sys_unit unit = sysUnitService.fetch(id);
        if (unit == null) {
            return Result.error(ResultCode.NULL_DATA_ERROR);
        }

        SysUnitVO vo = new SysUnitVO();
        BeanUtil.copyProperties(unit, vo);

        List<String> serviceOrderTypeList = Lists.newArrayList();
        if (StringUtils.isNotBlank(vo.getServiceOrderType())) {
            String[] split = vo.getServiceOrderType().split(",");
            serviceOrderTypeList = Lists.newArrayList(split);
        }
        vo.setServiceOrderTypeList(serviceOrderTypeList);

        List<Sys_unit_user> unitUserList = sysUnitUserService.query(Cnd.where("unitId", "=", id), "user");
        return Result.data(NutMap.NEW().addv("unit", vo).addv("unitUserList", unitUserList));
    }

    @At
    @Ok("json")
    @POST
    @SaCheckPermission("sys.manage.unit.update")
    @SLog(value = "修改单位:${unit.name}")
    @ApiOperation(name = "修改单位")
    @ApiFormParams(
            value = {
                    @ApiFormParam(name = "leader", description = "本单位领导"),
                    @ApiFormParam(name = "higher", description = "上级主管领导"),
                    @ApiFormParam(name = "assigner", description = "上级分管领导")
            },
            implementation = Sys_unit.class
    )
    @ApiResponses
    public Result<?> update(@Param("..") Sys_unit unit, @Param("leader") String leader,
                            @Param("higher") String higher, @Param("assigner") String assigner, HttpServletRequest req) {
        unit.setUpdatedBy(SecurityUtil.getUserId());
        sysUnitService.update(unit, Strings.splitIgnoreBlank(leader), Strings.splitIgnoreBlank(higher), Strings.splitIgnoreBlank(assigner));
        return Result.success();
    }

    @At("/get_sort_tree")
    @Ok("json")
    @GET
    @SaCheckPermission("sys.manage.unit")
    @ApiOperation(name = "Vue2获取待排序数据")
    @ApiImplicitParams
    @ApiResponses
    public Result<?> getSortTree(HttpServletRequest req) {
        Cnd cnd = Cnd.NEW();
        if (!StpUtil.hasRole(GlobalConstant.DEFAULT_SYSADMIN_ROLECODE)) {
            Sys_unit unit = sysUnitService.fetch(SecurityUtil.getUnitId());
            cnd.and("path", "like", unit.getPath() + "%");
        }
        cnd.asc("location").asc("path");
        List<Sys_unit> list = sysUnitService.query(cnd);
        NutMap nutMap = NutMap.NEW();
        for (Sys_unit unit : list) {
            if (unit.getParentId() == null) unit.setParentId("");
            List<Sys_unit> list1 = nutMap.getList(unit.getParentId(), Sys_unit.class);
            if (list1 == null) {
                list1 = new ArrayList<>();
            }
            list1.add(unit);
            nutMap.put(Strings.sNull(unit.getParentId()), list1);
        }
        return Result.data(getTree(nutMap, ""));
    }

    private List<NutMap> getTree(NutMap nutMap, String pid) {
        List<NutMap> treeList = new ArrayList<>();
        List<Sys_unit> subList = nutMap.getList(pid, Sys_unit.class);
        for (Sys_unit unit : subList) {
            NutMap map = Lang.obj2nutmap(unit);
            map.put("label", unit.getName());
            if (unit.isHasChildren() || (nutMap.get(unit.getId()) != null)) {
                map.put("children", getTree(nutMap, unit.getId()));
            }
            treeList.add(map);
        }
        return treeList;
    }

    @At("/sort")
    @Ok("json")
    @POST
    @SaCheckPermission("sys.manage.unit.update")
    @ApiOperation(name = "保存排序数据")
    @ApiFormParams({
            @ApiFormParam(name = "ids", description = "ids数组")
    })
    @ApiResponses
    public Result<?> sortDo(@Param("ids") String ids, HttpServletRequest req) {
        String[] unitIds = StringUtils.split(ids, ",");
        int i = 0;
        if (StpUtil.hasRole(GlobalConstant.DEFAULT_SYSADMIN_ROLECODE)) {
            sysUnitService.update(Chain.make("location", 0), Cnd.NEW());
        }
        for (String id : unitIds) {
            if (!Strings.isBlank(id)) {
                sysUnitService.update(Chain.make("location", i), Cnd.where("id", "=", id));
                i++;
            }
        }
        return Result.success();
    }

    @At("/search_user")
    @Ok("json")
    @POST
    @SaCheckPermission("sys.manage.unit")
    @ApiOperation(name = "查询单位用户")
    @ApiFormParams({
            @ApiFormParam(name = "query", description = "查询关键词"),
            @ApiFormParam(name = "unitId", description = "单位ID")
    })
    @ApiResponses
    public Result<?> searchUser(@Param("query") String query, @Param("unitId") String unitId, HttpServletRequest req) {
        return Result.data(sysUnitService.searchUser(query, unitId));
    }


    @At("/createcompany")
    @Ok("json")
    @POST
    @SaCheckPermission("sys.manage.unit.createcompany")
    @SLog(value = "新建单位:${unit.name}")
    @ApiOperation(name = "新建单位")
    @ApiFormParams(
            implementation = Sys_unit.class
    )
    @ApiResponses
    public Result<?> createcompany(@Param("..") Sys_unit unit, HttpServletRequest req) {
        unit.setCreatedBy(SecurityUtil.getUserId());
        unit.setDisabled(false);
        unit.setLocation(0);
        unit.setHasChildren(true);
        unit.setDelFlag(false);
        unit.setParentId("");
        unit.setPath(UUID.randomUUID().toString());
        sysUnitService.insert(unit);

        //新建分组
        Sys_group group = new Sys_group();
        group.setUnitId(unit.getId());
        group.setCreatedBy(SecurityUtil.getUserId());
        group.setName(unit.getName());
        group.setUnitPath(sysUnitService.fetch(unit.getId()).getPath());
        sysGroupService.insert(group);

        //新建普通角色
        Sys_role role = new Sys_role();
        //String uId = UUID.randomUUID().toString().replaceAll("-","");
        role.setGroupId(group.getId());
        role.setUnitId(unit.getId());
        String uIdCode = UUID.randomUUID().toString().replaceAll("-", "");
        role.setCode("publics");
        role.setDisabled(false);
        role.setCreatedBy(SecurityUtil.getUserId());
        role.setName("普通角色");
        sysRoleService.insert(role);

        String[] ids = Strings.splitIgnoreBlank("9d010f91044b4d76ad4873c3fb0b1210,b414adb6369041a6a5d0c1f7992c1b19,2e016f846b8a4489b2044cca4eb562cc,2beb430e1aa84f72bfd3a9a5732b8db2,a659196dc29243db8bd749b879d9466f,76d5b22c621c448394611c93a523368e,ccdc628c6c704e88b4d2b3312622550f");
        if (GlobalConstant.DEFAULT_SYSADMIN_ROLECODE.equals(uIdCode) && GlobalConstant.DEFAULT_PLATFORM_APPID.equals("PLATFORM") && ids.length == 0) {
            return Result.error("角色权限不可为空,可能会造成无法登录系统");
        }
        sysRoleService.saveMenu(role.getId(), "PLATFORM", ids);


        Sys_role adminrole = new Sys_role();
        //String adminuId = UUID.randomUUID().toString().replaceAll("-","");
        adminrole.setGroupId(group.getId());
        adminrole.setUnitId(unit.getId());
        String adminuIdCode = UUID.randomUUID().toString().replaceAll("-", "");
        adminrole.setCode("admin");
        adminrole.setDisabled(false);
        adminrole.setCreatedBy(SecurityUtil.getUserId());
        adminrole.setName("社区管理员");
        sysRoleService.insert(adminrole);

        String[] adminids = Strings.splitIgnoreBlank("fc348d93d9454d66be5e486dbef2d6f8,3c0a52058051471e991d6a0a73572200,3044cbbf64d34ad1a139a3cb3034f885,451b85d1d84449e9aedd7fc7ab63c42b,ed5f07e5d5154826b3381a75fe3b0747,9d010f91044b4d76ad4873c3fb0b1210,b414adb6369041a6a5d0c1f7992c1b19,2e016f846b8a4489b2044cca4eb562cc,2beb430e1aa84f72bfd3a9a5732b8db2,a659196dc29243db8bd749b879d9466f,76d5b22c621c448394611c93a523368e,ccdc628c6c704e88b4d2b3312622550f");
        if (GlobalConstant.DEFAULT_SYSADMIN_ROLECODE.equals(adminuIdCode) && GlobalConstant.DEFAULT_PLATFORM_APPID.equals("PLATFORM") && adminids.length == 0) {
            return Result.error("超级管理员角色权限不可为空,可能会造成无法登录系统");
        }
        sysRoleService.saveMenu(adminrole.getId(), "PLATFORM", adminids);

        return Result.success();
    }

    @At("/createCompanyExhaustive")
    @Ok("json")
    @POST
    @SLog(value = "新建单位:${unit.name}")
    @ApiResponses
    @SaCheckPermission("sys.manage.unit.createcompany")
    public Result<?> createCompanyExhaustive(@Param("..") SysUnitUpdateDTO unit) {
        log.info("unitController createCompanyExhaustive param: {}", JSONObject.toJSONString(unit));
        sysUnitService.createCompanyExhaustive(unit, SecurityUtil.getUserId());
        return Result.success();
    }

    @At("/updateCompanyExhaustive")
    @Ok("json")
    @POST
    @SLog(value = "新建单位:${unit.name}")
    @ApiResponses
    @SaCheckPermission("sys.manage.unit.createcompany")
    public Result<?> updateCompanyExhaustive(@Param("..") SysUnitUpdateDTO unit) {
        try {
            String userId = SecurityUtil.getUserId();
            sysUnitService.updateCompanyExhaustive(unit, userId);
        } catch (Exception e) {
            return Result.error(e.getMessage());
        }
        return Result.success();
    }

    /**
     * 单位管理列表查询（用于后台管理系统）
     */
    @At("/listUnitForAdmin")
    @Ok("json")
    @POST
    @ApiOperation(name = "后台管理系统单位管理列表查询")
    @ApiFormParams(
            value = {
                    @ApiFormParam(name = "pageNo", example = "1", description = "页码", type = "integer"),
                    @ApiFormParam(name = "pageSize", example = "10", description = "页大小", type = "integer"),
                    @ApiFormParam(name = "pageOrderName", example = "createdAt", description = "排序字段"),
                    @ApiFormParam(name = "pageOrderBy", example = "descending", description = "排序方式")
            },
            implementation = SysUnitUpdateDTO.class
    )
    @ApiResponses(
            implementation = SysUnitVO.class
    )
    @SLog(tag = "后台管理系统单位管理列表查询", value = "${args[0]}")
    @SaCheckLogin
    public Result<?> listUnitForAdmin(@Param("..") SysUnitUpdateDTO bean,
                                      @Param("pageNo") int pageNo,
                                      @Param("pageSize") int pageSize,
                                      @Param("pageOrderName") String pageOrderName,
                                      @Param("pageOrderBy") String pageOrderBy) {
        return Result.success(sysUnitService.listUnitForAdmin(bean, pageNo, pageSize, pageOrderName, pageOrderBy));
    }

    /**
     * 单位信息修改（后台管理系统）
     * @param unit
     * @return
     */
    @At("/updateUnitForAdmin")
    @Ok("json")
    @POST
    @SLog(tag = "后台管理系统单位信息修改", value = "${args[0]}")
    @ApiResponses
    @SaCheckLogin
    public Result<?> updateUnitForAdmin(@Param("..") SysUnitUpdateDTO unit) {
        return Result.success(sysUnitService.updateUnitForAdmin(unit));
    }

    @At("/deleteForAdmin/{id}")
    @Ok("json")
    @DELETE
    @SLog(value = "删除单位:")
    @ApiOperation(name = "删除单位")
    @ApiImplicitParams(
            {
                    @ApiImplicitParam(name = "id", description = "主键ID", in = ParamIn.PATH)
            }
    )
    @ApiResponses
    @SaCheckLogin
    public Result<?> deleteForAdmin(String id) {
        Sys_unit unit = sysUnitService.fetch(id);
        if (unit == null) {
            return Result.error(ResultCode.NULL_DATA_ERROR);
        }
        sysUnitService.deleteForAdmin(id);
        return Result.success();
    }

    /**
     * 社区列表查询
     */
    @At
    @Ok("json")
    @POST
    @ApiOperation(name = "社区列表查询")
    @ApiFormParams(implementation = SysUnitUpdateDTO.class)
    @ApiResponses(
            implementation = List.class
    )
    @SLog(tag = "社区列表查询", value = "${args[0]}")
    @SaCheckLogin
    public Result<?> queryCommunityList(@Param("..") SysUnitUpdateDTO bean) {
        return Result.success(sysUnitService.queryCommunityList(bean));
    }

    /**
     * 批量修改单位信息（后台管理系统）
     * @param unit
     * @return
     */
    @At("/batchUpdateForAdmin")
    @Ok("json")
    @POST
    @SLog(tag = "批量修改单位信息", value = "${args[0]}")
    @ApiResponses
    @SaCheckLogin
    public Result<?> batchUpdateForAdmin(@Param("ids") List<String> ids, @Param("..") SysUnitUpdateDTO unit) {
        return Result.data(sysUnitService.batchUpdateForAdmin(ids, unit));
    }

    @At
    @Ok("json")
    @POST
    @ApiOperation(name = "unit清洗")
    @ApiImplicitParams(
            value = {
                    @ApiImplicitParam(name = "name", description = "主键ID", in = ParamIn.PATH)
            }
    )
    @ApiResponses
    public Result<?> unitDataClean(@Param("level") String level) {
        sysUnitService.unitDataClean(level);
        return Result.success();
    }


    @At
    @Ok("json")
    @POST
    @ApiOperation(name = "unit清洗")
    @ApiImplicitParams(
            value = {
                    @ApiImplicitParam(name = "name", description = "主键ID", in = ParamIn.PATH)
            }
    )
    @ApiResponses
    public Result<?> unitDataCleanPath(@Param("level") String level) {
        sysUnitService.unitDataCleanPath(level);
        return Result.success();
    }

    @At
    @Ok("json")
    @POST
    @ApiOperation(name = "unit清洗")
    @ApiImplicitParams(
            value = {
                    @ApiImplicitParam(name = "name", description = "主键ID", in = ParamIn.PATH)
            }
    )
    @ApiResponses
    public Result<?> unitDataCleanHasChild(@Param("level") String level) {
        sysUnitService.unitDataCleanHasChild(level);
        return Result.success();
    }

    @At
    @Ok("json")
    @GET
    @ApiOperation(name = "查询当前单位树")
    @ApiResponses
    @SaCheckLogin
    public Result<?> queryUnitTree(@Param("unitId") String unitId) {
        unitId = StringUtils.isEmpty(unitId) ? SecurityUtil.getUnitId() : unitId;
        Sys_unit unit = sysUnitService.queryUnitTree(unitId, null);
        return Result.data(unit);
    }
}
